package com.dede.locallib;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 通过app_process运行java进程的demo
 * <p/>
 * 将jar包打为dex包
 * dx --dex --output=dream.dex localLib.jar
 * <p>
 * 将dex包导入手机
 * <p>
 * 设置Class Path
 * export CLASSPATH=/storage/emulated/0/dex.dex
 * <p>
 * 开启进程
 * exec app_process /storage/emulated/0 com.dede.locallib.Helper
 */
public class Helper {

    private static final String TAG = "ScreenSaverHelper";

    public static void main(String... args) {
        int length = args.length;
        StringBuilder builder = new StringBuilder("main args：(length=")
                .append(String.valueOf(length))
                .append(")\t");
        for (String arg : args) {
            builder.append(arg).append("\t");
        }
        ALog.i(TAG, builder.toString());

        String arg = length == 0 ? "dream" : args[0];
        switch (arg) {
            case "dream":
                dream();
                break;
            case "awaken":
                awaken();
                break;
        }
    }

    /**
     * 唤醒屏保
     */
    private static void awaken() {
        try {
            invoke("awaken");

            System.out.println("end");
            ALog.i(TAG, "end");
        } catch (ClassNotFoundException | NoSuchMethodException |
                IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            System.out.println("exception");
            ALog.i(TAG, e.getMessage());
        }
    }

    /**
     * 反射调用如下方法，开启屏保
     * <p>IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE)).dream();
     * <p>查看系统源码
     * <p><a href="http://androidxref.com/7.1.2_r36/xref/frameworks/base/packages/
     * SettingsLib/src/com/android/settingslib/dream/DreamBackend.java">
     * com.android.settingslib.dream.DreamBackend#DreamBackend</a>
     * <p><a href="http://androidxref.com/7.1.2_r36/xref/frameworks/base/packages/
     * SettingsLib/src/com/android/settingslib/dream/DreamBackend.java#startDreaming">
     * com.android.settingslib.dream.DreamBackend#dream</a>
     */
    private static void dream() {
        try {
            invoke("dream");

            System.out.println("end");
            ALog.i(TAG, "end");
        } catch (ClassNotFoundException | NoSuchMethodException |
                IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            System.out.println("exception");
            ALog.i(TAG, e.getMessage());
        }
    }

    /**
     * 反射调用IDreamManager的方法
     * <p>
     * IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE))
     * <p/>公有方法
     * <p>asBinder
     * <p>asInterface android.os.IBinder
     * <p>attachInterface android.os.IInterface java.lang.String
     * <p>awaken
     * <p>blockUntilThreadAvailable
     * <p>clearCallingIdentity
     * <p>dream
     * <p>dump java.io.FileDescriptor [Ljava.lang.String;
     * <p>dumpAsync java.io.FileDescriptor [Ljava.lang.String;
     * <p>finishSelf android.os.IBinder boolean
     * <p>flushPendingCommands
     * <p>getCallingPid
     * <p>getCallingUid
     * <p>getCallingUserHandle
     * <p>getDefaultDreamComponent
     * <p>getDreamComponents
     * <p>getInterfaceDescriptor
     * <p>getLidState
     * <p>getThreadStrictModePolicy
     * <p>isBinderAlive
     * <p>isDozing
     * <p>isDreaming
     * <p>isProxy android.os.IInterface
     * <p>joinThreadPool
     * <p>linkToDeath android.os.IBinder$DeathRecipient int
     * <p>onTransact int android.os.Parcel android.os.Parcel int
     * <p>pingBinder
     * <p>queryLocalInterface java.lang.String
     * <p>restoreCallingIdentity long
     * <p>setDreamComponents [Landroid.content.ComponentName;
     * <p>setDumpDisabled java.lang.String
     * <p>setLidState int
     * <p>setThreadStrictModePolicy int
     * <p>startDozing android.os.IBinder int int
     * <p>stopDozing android.os.IBinder
     * <p>testDream android.content.ComponentName
     * <p>transact int android.os.Parcel android.os.Parcel int
     * <p>unlinkToDeath android.os.IBinder$DeathRecipient int
     * <p/>私有方法
     * <p>asBinder
     * <p>onTransact
     * <p>asInterface
     */
    private static void invoke(String methodName) throws ClassNotFoundException,
            NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        // 获取ServiceManager的IBinder对象，ServiceManager.getService(DREAM_SERVICE)
        Class<?> smClass = ReflectUtil.clazz("android.os.ServiceManager");
        Method getServiceMethod = ReflectUtil.method(smClass, "getService", String.class);
        // android.service.dreams.DreamService#DREAM_SERVICE = "dreams"
        Object iBinder = getServiceMethod.invoke(null, "dreams");

        // 获取IDreamManager远程代理对象，IDreamManager.Stub.asInterface(IBinder)
        Class<?> iDmSClass = ReflectUtil.clazz("android.service.dreams.IDreamManager$Stub");
        Class<?> iBinderClass = ReflectUtil.clazz("android.os.IBinder");
        Method asInterfaceMethod = ReflectUtil.method(iDmSClass, "asInterface", iBinderClass);
        Object dream = asInterfaceMethod.invoke(null, iBinder);

        // 调用方法
        Method dreamMethod = ReflectUtil.method(dream.getClass(), methodName);
        dreamMethod.invoke(dream);
    }

}
